package code.parser;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Java C++代码解析器<br>
 * 代码片段.<br>
 * 如namespace{} ,静态代码段{} ,类{} ,方法{}等花括号包裹开来的文本区域,称为代码片段. <br>
 * 也有例外如成员变量是用;号分隔也可以称之为代码片段.
 * 
 * @author Ge Liang
 *
 */
public abstract class Snippet {
	
	/**
	 * C# 语言
	 */
	public static final String CS = ".cs";
	/**
	 * JAVA 语言
	 */
	public static final String JAVA = ".java";
	
	/**
	 * 源代码
	 */
	public String source;
	/**
	 * 片段的名字
	 */
	public String name;
	/**
	 * 片段的内容
	 */
	public String snippet;
	/**
	 * 目标代码
	 */
	public String targetSource;
	/**
	 * 目标代码文件的后缀
	 */
	public String tragetSourceSuffix = JAVA;
	/**
	 * 匹配当前代码片段的正则表达式
	 */
	public String regularExpression;
	/**
	 * 访问权限修饰符 public default private
	 */
	public String access = "public";
	/**
	 * 是否是有final/const修饰符
	 */
	public boolean isConst;

	public Snippet() {
	}

	public Snippet(File file) {
		source = readSourcefile(file);
	}

	public Snippet(String source) {
		this.source = source;
	}

	/**
	 * 正则表达式匹配源代码中的代码片段
	 * 
	 * @param source
	 *            源代码
	 * @return 匹配的代码片段,剥离掉了{};失败返回null
	 */
	public abstract List<? extends Snippet> regularExpressionMatch(String source);

	/**
	 * 从文件中读取源代码
	 * 
	 * @param file
	 * @return
	 */
	public static String readSourcefile(File file) {
		String result = "";
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			String s = null;
			while ((s = br.readLine()) != null) {
				result = result + "\n" + s;
			}
			br.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	public static Map<String, String> getAllDefine(File hfile) {
		BufferedReader fis = null;
		HashMap<String, String> map = new HashMap<String, String>();
		try {
			fis = new BufferedReader(new FileReader(hfile));
			String txt = fis.readLine();
			while (txt != null) {
				if (txt.startsWith("#define")) {
					String re1 = "(#)"; // Any Single Character 1
					String re2 = "(define)"; // Word 1
					String re3 = "(\\s+)"; // White Space 1
					String re4 = "([a-zA-Z_][a-zA-Z0-9_]*)"; // Variable Name 1
					String re5 = "(\\s+)*"; // White Space 2
					String re6 = "([a-zA-Z_0-9][()a-zA-Z0-9_\"]*)*"; // Variable
																		// Name
																		// 2

					Pattern p = Pattern.compile(re1 + re2 + re3 + re4 + re5
							+ re6, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
					Matcher m = p.matcher(txt);
					while (m.find()) {
						String var1 = m.group(4);
						String var2 = m.group(6);
						map.put(var1, var2 == null ? "" : var2);
					}

				}

				txt = fis.readLine();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if (fis!=null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return map;
	}
}
